/*
 * lsdb_interface.c
 *
 *  Created on: 2009-3-31
 *      Author: Octopus
 */
#include <assert.h>

#include <cmn/list.h>
#include "cmn/err_code.h"

#include <lsdb/private/lsdb_inner.h>

int cr_lsdb_router_add(const struct cr_lsdb_router* router, id_t lsdb_handle)
{
	struct router_node* p;
	assert(router->id != 0);
	assert(lsdb_router_find(router->id, &p, (struct lsdb*)lsdb_handle) == NOT_FOUND_ERR);
	return lsdb_router_add(router, &p, (struct lsdb*)lsdb_handle);
}
int cr_lsdb_router_find(struct cr_lsdb_router* router, id_t lsdb_handle)
{
	int r;
	struct router_node* p;
	if(router->id == 0) return NOT_FOUND_ERR;
	r = lsdb_router_find(router->id, &p, (struct lsdb*)lsdb_handle);
	if(!r)
		*router = p->data;
	return r;
}
int cr_lsdb_router_update(const struct cr_lsdb_router* router, id_t lsdb_handle)
{
	int r;
	struct router_node* p;
	assert(router->id != 0);
	r = lsdb_router_find(router->id, &p, (struct lsdb*)lsdb_handle);
	if(!r)
		p->data = *router;
	return r;
}
int cr_lsdb_link_state_add(const struct cr_lsdb_link_state* link, id_t lsdb_handle)
{
	struct link_state* result;
	assert(!(link->key.rt_id == 0));
	assert(NOT_FOUND_ERR == lsdb_link_state_find(&link->key, &result, (struct lsdb*)lsdb_handle));
	return lsdb_link_state_add(link, &result, (struct lsdb*)lsdb_handle);
}

int cr_lsdb_link_state_find(const struct link_state_key* key, struct cr_lsdb_link_state* link, id_t lsdb_handle)
{
	int r;
	struct link_state* result;
	if(key->rt_id == 0) return NOT_FOUND_ERR;

	r = lsdb_link_state_find(key, &result, (struct lsdb*)lsdb_handle);
	if(!r)
	{
		// *link = result->data;
		memcpy(link,&(result->data),sizeof(struct cr_lsdb_link_state));
		link->shadow	= result->data.shadow;
	}
	return r;
}

int cr_lsdb_neighbour_info_find(struct link_state_key* key, id_t lsdb_handle)
{
	struct cr_list_head * ptr;
	struct router_node *node;
	struct link_state* entry;
	struct lsdb* cr_lsdb;

	cr_lsdb = (struct lsdb*)lsdb_handle;
	int r = lsdb_router_find(key->rt_id, &node, cr_lsdb);
	if(r)
		return r;
	for(ptr = node->links_state_head.next; ptr != &node->links_state_head; ptr = ptr->next)
	{
		entry = CR_LIST_ENTRY(ptr, struct link_state, rt_ptrs);
		if(entry->data.key.if_id == key->if_id)
		{
			key->n_rt_id = entry->data.key.n_rt_id;
			key->n_if_id = entry->data.key.n_if_id;
			return NO_ERR;
		}
	}
	return NOT_FOUND_ERR;
}

int cr_lsdb_ethid_info_find_by_nrt_id(struct link_state_key* key, id_t lsdb_handle)
{
	struct cr_list_head * ptr;
	struct router_node *node;
	struct link_state* entry;
	struct lsdb* cr_lsdb;

	cr_lsdb = (struct lsdb*)lsdb_handle;
	int r = lsdb_router_find(key->rt_id, &node, cr_lsdb);
	if(r)
		return r;
	for(ptr = node->links_state_head.next; ptr != &node->links_state_head; ptr = ptr->next)
	{
		entry = CR_LIST_ENTRY(ptr, struct link_state, rt_ptrs);
		if(entry->data.key.n_rt_id == key->n_rt_id)
		{
			key->if_id = entry->data.key.if_id;
			key->n_if_id = entry->data.key.n_if_id;
			return NO_ERR;
		}
	}
	return NOT_FOUND_ERR;
}



int cr_lsdb_link_state_update(const struct cr_lsdb_link_state* link, id_t lsdb_handle)
{
	int r;
	struct link_state* result;
	assert(!(link->key.rt_id == 0));

	r = lsdb_link_state_find(&link->key, &result, (struct lsdb*)lsdb_handle);
	if(!r)
	{
		//result->data = *link;
		//printf("\n update link state %p\n",link->shadow);
		memcpy(&(result->data),link,sizeof(struct cr_lsdb_link_state));
	}
	return r;
}
inline int cr_lsdb_get_routers_count(id_t lsdb_handle)
{
	return ((struct lsdb*)lsdb_handle)->routers_count;
}
inline int cr_lsdb_get_link_states_count(id_t lsdb_handle)
{
	return ((struct lsdb*)lsdb_handle)->links_state_count;
}

